package com.ou.csbs.capstone.tools;

import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.globes.Globe;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import com.ou.csbs.capstone.gridlines.ExtendedUTMLayer;
import com.ou.csbs.capstone.gridlines.UTMCoord;
import com.ou.csbs.capstone.views.menu.StatusBar;
import com.ou.csbs.capstone.views.worldwind.WorldWindCanvas;

/**
 * The StatusBarTool is not a required tool. It serves to report the current mouse position based on what grid system is currently active. Coordinates default to Lat/Lon, but will change to UTM
 * if the UTM layer is active, and EUTM if the EUTM layer is active. String parsing is performed to clean up the positional data for ease of reading, as well as to identify Latitude bands in UTM
 * and EUTM. EUTM coordinates are based on the current active zone. If the UTM or EUTM mouse coordinates are invalid, the tool will simply report "Outside of UTM/EUTM bounds"
 * 
 * @author Senior Capstone
 */
public class StatusBarTool extends MouseAdapter {
	public StatusBarTool(){
	}

	@Override
	public void mouseMoved(MouseEvent event){
		Position position = WorldWindCanvas.getWorldWindow().getCurrentPosition();
		if(position != null){
			if(WorldWindCanvas.getWorldWindModel().getLayers().getLayerByName("UTMLayer") != null &&
					WorldWindCanvas.getWorldWindModel().getLayers().getLayerByName("UTMLayer").isEnabled()){
				StatusBar.setLocationText(parseToUTMCoord(position));
			}else if(WorldWindCanvas.getWorldWindModel().getLayers().getLayerByName("ExtendedUTMLayer") != null && 
					WorldWindCanvas.getWorldWindModel().getLayers().getLayerByName("ExtendedUTMLayer").isEnabled()){
				StatusBar.setLocationText(parseToEUTMCoord(position));
			}else{
				StatusBar.setLocationText(parseToLatLongCoord(position));
			}
		}else{
			StatusBar.setLocationText(" ");
		}
	}
	private String parseToLatLongCoord(Position position){
		return "Lat:" + String.format("%.7g%n", position.getLatitude().getDegrees()) + "\u00B0, " +
				"Lon:" + String.format("%.7g%n", position.getLongitude().getDegrees()) + "\u00B0";
	}
	private String parseToUTMCoord(Position position){
		if(position.latitude.getDegrees() >= -80 && position.latitude.getDegrees() <= 84){
			UTMCoord utm = UTMCoord.fromLatLon(position.latitude, position.longitude, WorldWindCanvas.getWorldWindModel().getGlobe());
			String quadrant = getLatBand(position);
			if(quadrant != null){
				return utm.getZone() + " " + quadrant + " " + String.format("%08.0f",utm.getEasting()) + "E " + String.format("%08.0f", utm.getNorthing()) + "N";
			}
		}
		return "Outside of UTM bounds";
	}
	private String parseToEUTMCoord(Position position){
		if(position.latitude.getDegrees() >= -80 && position.latitude.getDegrees() <= 84){
			UTMCoord eutmReference = ((ExtendedUTMLayer) WorldWindCanvas.getWorldWindModel().getLayers().getLayerByName("ExtendedUTMLayer")).getReferenceCoord();
			Globe globe = WorldWindCanvas.getWorldWindModel().getGlobe();
			UTMCoord eutmCoord;
			try{
				eutmCoord = UTMCoord.fromLatLon(eutmReference.getZone(), position.getLatitude(), position.getLongitude(), globe);
			}catch(Exception e){
				return "Outside of EUTM bounds";
			}
			String quadrant = getLatBand(position);
			if(quadrant != null){
				return eutmCoord.getZone() + " " + quadrant + " " + String.format("%08.0f",eutmCoord.getEasting()) + "E " + String.format("%08.0f", eutmCoord.getNorthing()) + "N";
			}
		}
		return "Outside of EUTM bounds";
	}
	
	private String getLatBand(Position position){
		String quadrant = null;
		if(position.latitude.getDegrees() > 0){
			int q = (int) Math.floor(position.latitude.getDegrees() / 8);
			if(position.latitude.getDegrees() >= 80 && position.latitude.getDegrees() <= 84){
				quadrant = "X";
			}else{
				switch(q){
				case 0: quadrant = "N"; break;
				case 1: quadrant = "P"; break;
				case 2: quadrant = "Q"; break;
				case 3: quadrant = "R"; break;
				case 4: quadrant = "S"; break;
				case 5: quadrant = "T"; break;
				case 6: quadrant = "U"; break;
				case 7: quadrant = "V"; break;
				case 8: quadrant = "W"; break;
				case 9: quadrant = "X"; break; 
				}
			}
		}else{
			int q = (int) Math.floor(Math.abs(position.latitude.getDegrees()) / 8);
			switch(q){
			case 0: quadrant = "M"; break;
			case 1: quadrant = "L"; break;
			case 2: quadrant = "K"; break;
			case 3: quadrant = "J"; break;
			case 4: quadrant = "H"; break;
			case 5: quadrant = "G"; break;
			case 6: quadrant = "F"; break;
			case 7: quadrant = "E"; break;
			case 8: quadrant = "D"; break;
			case 9: quadrant = "C"; break; 
			}

		}
		return quadrant;
	}
}
